package com.tzkyzj.tiremanager.service;

import com.tzkyzj.tiremanager.entity.Tire;
import com.tzkyzj.tiremanager.entity.TirePhoto;
import com.tzkyzj.tiremanager.repository.TirePhotoRepository;
import com.tzkyzj.tiremanager.repository.TireRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;
//import javax.transaction.Transactional;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Transactional
public class TirePhotoService {
    private static final Logger log = LoggerFactory.getLogger(TirePhotoService.class);

    @Autowired
    private TirePhotoRepository tirePhotoRepository;

    @Autowired
    private TireRepository tireRepository;

    @Value("${app.upload.path:uploads}")
    private String uploadPath;


    public void saveSwapPhotos(Long tireId, MultipartFile[] photos, String description, String operationType) {
        log.info("开始保存调胎照片，轮胎ID: {}, 操作类型: {}, 描述: {}", tireId, operationType, description);

        // 验证轮胎是否存在
        Tire tire = tireRepository.findById(tireId)
                .orElseThrow(() -> new RuntimeException("轮胎不存在，ID: " + tireId));

        // 创建调胎照片目录
        String swapPhotoDir = uploadPath + "/tires/" + tireId + "/swap";
        File directory = new File(swapPhotoDir);
        if (!directory.exists()) {
            boolean created = directory.mkdirs();
            if (!created) {
                throw new RuntimeException("无法创建调胎照片目录: " + swapPhotoDir);
            }
        }

        // 保存每张照片
        for (MultipartFile photo : photos) {
            if (!photo.isEmpty()) {
                try {
                    // 生成唯一文件名
                    String originalFileName = photo.getOriginalFilename();
                    String fileExtension = "";
                    if (originalFileName != null && originalFileName.contains(".")) {
                        fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
                    }
                    String uniqueFileName = System.currentTimeMillis() + "_" + UUID.randomUUID() + fileExtension;

                    // 保存文件到磁盘
                    Path filePath = Paths.get(swapPhotoDir, uniqueFileName);
                    Files.copy(photo.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);

                    // 创建照片记录
                    TirePhoto tirePhoto = new TirePhoto();
                    tirePhoto.setTire(tire);
                    tirePhoto.setFileName(originalFileName);
                    tirePhoto.setFilePath(filePath.toString());
                    tirePhoto.setFileSize(photo.getSize());
                    tirePhoto.setContentType(photo.getContentType());
                    tirePhoto.setUploadDate(LocalDateTime.now());

                    // 设置照片类型和描述
                    if ("swap".equals(operationType)) {
                        tirePhoto.setPhotoType("SWAP"); // 正常调胎照片
                    } else if ("scrap".equals(operationType)) {
                        tirePhoto.setPhotoType("SCRAP"); // 调胎报废照片
                    }
                    tirePhoto.setDescription(description);

                    tirePhotoRepository.save(tirePhoto);

                    log.info("成功保存调胎照片: {}", filePath);

                } catch (Exception e) {
                    log.error("保存调胎照片失败: {}", e.getMessage());
                    throw new RuntimeException("保存调胎照片失败: " + e.getMessage(), e);
                }
            }
        }
    }





    public void saveRepairPhotos(Long tireId, MultipartFile[] photos, String repairRecord) {
        log.info("开始保存修补照片，轮胎ID: {}, 修补记录: {}", tireId, repairRecord);

        // 修复：从 Optional 中获取 Tire 对象
        Tire tire = tireRepository.findById(tireId)
                .orElseThrow(() -> new RuntimeException("轮胎不存在，ID: " + tireId));

        // 创建修补照片目录
        String repairPhotoDir = uploadPath + "/tires/" + tireId + "/repair";
        File directory = new File(repairPhotoDir);
        if (!directory.exists()) {
            boolean created = directory.mkdirs();
            if (!created) {
                throw new RuntimeException("无法创建修补照片目录: " + repairPhotoDir);
            }
        }

        // 保存每张照片
        for (MultipartFile photo : photos) {
            if (!photo.isEmpty()) {
                try {
                    // 生成唯一文件名
                    String originalFileName = photo.getOriginalFilename();
                    String fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
                    String uniqueFileName = System.currentTimeMillis() + "_" + UUID.randomUUID() + fileExtension;

                    // 保存文件到磁盘
                    Path filePath = Paths.get(repairPhotoDir, uniqueFileName);
                    Files.copy(photo.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);

                    // 创建照片记录
                    TirePhoto tirePhoto = new TirePhoto();
                    tirePhoto.setTire(tire);
                    tirePhoto.setFileName(originalFileName);
                    tirePhoto.setFilePath(filePath.toString());
                    tirePhoto.setFileSize(photo.getSize());
                    tirePhoto.setContentType(photo.getContentType());

                    // 使用 LocalDateTime
                    tirePhoto.setUploadDate(LocalDateTime.now());

                    tirePhoto.setPhotoType("REPAIR"); // 标记为修补照片
                    tirePhoto.setDescription("修补记录: " + repairRecord); // 添加修补描述

                    tirePhotoRepository.save(tirePhoto);

                    log.info("成功保存修补照片: {}", filePath);

                } catch (Exception e) {
                    log.error("保存修补照片失败: {}", e.getMessage());
                    throw new RuntimeException("保存修补照片失败: " + e.getMessage(), e);
                }
            }
        }
    }


    /**
     * 在同一个事务中保存照片 - 修复数组处理问题
     */
    @Transactional
    public List<TirePhoto> savePhotosInSameTransaction(Long tireId, MultipartFile[] files) {
        log.info("在事务中批量保存照片，轮胎ID: {}, 文件数量: {}", tireId, files != null ? files.length : 0);

        // 参数验证
        if (files == null || files.length == 0) {
            log.warn("没有照片文件需要保存");
            return Collections.emptyList();
        }

        List<String> savedFilePaths = new ArrayList<>();
        List<TirePhoto> photosToSave = new ArrayList<>();

        try {
            Tire tire = tireRepository.findById(tireId)
                    .orElseThrow(() -> new RuntimeException("轮胎不存在: " + tireId));

            String uploadDir = prepareUploadDirectory(tireId);

            // 处理每个文件
            for (MultipartFile file : files) {
                if (!file.isEmpty()) {
                    try {
                        String filePath = saveSingleFileToDisk(file, uploadDir);
                        savedFilePaths.add(filePath);

                        TirePhoto photo = createTirePhoto(file, tire, filePath);
                        photosToSave.add(photo);
                        log.info("成功保存文件到磁盘: {}", filePath);
                    } catch (Exception e) {
                        log.error("保存单个文件失败: {}", e.getMessage());
                        // 继续处理其他文件
                    }
                }
            }

            // 批量保存到数据库
            if (!photosToSave.isEmpty()) {
                List<TirePhoto> savedPhotos = tirePhotoRepository.saveAll(photosToSave);
                log.info("批量保存照片到数据库成功，照片数量: {}", savedPhotos.size());
                return savedPhotos;
            } else {
                log.warn("没有照片需要保存到数据库");
                return Collections.emptyList();
            }

        } catch (Exception e) {
            // 事务回滚时清理已保存的文件
            cleanupFilesOnFailure(savedFilePaths);
            log.error("批量保存照片失败", e);
            throw new RuntimeException("保存照片失败: " + e.getMessage(), e);
        }
    }

    /**
     * 准备上传目录
     */
    private String prepareUploadDirectory(Long tireId) throws IOException {
        String uploadDir = getAbsoluteUploadPath() + "/tires/" + tireId;
        File directory = new File(uploadDir);
        if (!directory.exists()) {
            boolean created = directory.mkdirs();
            if (!created) {
                throw new IOException("无法创建目录: " + directory.getAbsolutePath());
            }
        }
        return uploadDir;
    }

    /**
     * 创建轮胎照片实体
     */
    private TirePhoto createTirePhoto(MultipartFile file, Tire tire, String filePath) {
        TirePhoto photo = new TirePhoto();
        photo.setTire(tire);
        photo.setFileName(file.getOriginalFilename());
        photo.setFilePath(filePath);
        photo.setFileSize(file.getSize());
        photo.setContentType(file.getContentType());
        photo.setUploadDate(LocalDateTime.now());
        photo.setPhotoType("GENERAL");
        photo.setDescription("批量添加轮胎时上传的照片");
        return photo;
    }

    /**
     * 保存单个文件到磁盘
     */
    private String saveSingleFileToDisk(MultipartFile file, String uploadDir) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String fileExtension = getFileExtension(originalFilename);
        String uniqueFilename = System.currentTimeMillis() + "_" + UUID.randomUUID() + fileExtension;
        String filePath = uploadDir + File.separator + uniqueFilename;

        Files.copy(file.getInputStream(), Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);
        log.info("文件保存成功: {}", filePath);
        return filePath;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || !filename.contains(".")) {
            return ".jpg"; // 默认扩展名
        }
        return filename.substring(filename.lastIndexOf("."));
    }

    /**
     * 失败时清理文件
     */
    private void cleanupFilesOnFailure(List<String> filePaths) {
        if (filePaths == null || filePaths.isEmpty()) {
            return;
        }

        for (String filePath : filePaths) {
            try {
                Files.deleteIfExists(Paths.get(filePath));
                log.debug("清理文件: {}", filePath);
            } catch (IOException e) {
                log.warn("清理文件失败: {}", filePath, e);
            }
        }
    }

    /**
     * 获取绝对上传路径
     */
    private String getAbsoluteUploadPath() {
        String projectRoot = System.getProperty("user.dir");
        String configuredPath = this.uploadPath;

        if (configuredPath.startsWith("/") || configuredPath.contains(":")) {
            return configuredPath;
        } else {
            return projectRoot + File.separator + configuredPath;
        }
    }






    /**
     * 保存照片 - 使用强制在现有事务中
     */
    @Transactional(propagation = Propagation.MANDATORY)
    public List<TirePhoto> savePhotos(Long tireId, MultipartFile[] files) {
        log.info("=== 开始保存照片 (强制在现有事务中) ===");
        log.info("轮胎ID: {}, 文件数量: {}", tireId, files != null ? files.length : 0);

        List<TirePhoto> savedPhotos = new ArrayList<>();

        try {
            // 首先验证轮胎是否存在
            Tire tire = tireRepository.findById(tireId)
                    .orElseThrow(() -> new RuntimeException("轮胎不存在，ID: " + tireId));
            log.info("找到轮胎: {}, ID: {}", tire.getTireNumber(), tire.getId());

            // 检查文件数组
            if (files == null || files.length == 0) {
                log.warn("没有需要保存的照片文件");
                return savedPhotos;
            }

            // 获取上传路径
            String absoluteUploadPath = getAbsoluteUploadPath();
            String tireUploadDir = absoluteUploadPath + "/tires/" + tireId;
            File directory = new File(tireUploadDir);

            log.info("绝对上传路径: {}", absoluteUploadPath);
            log.info("轮胎上传目录: {}", tireUploadDir);

            // 创建目录
            if (!directory.exists()) {
                boolean created = directory.mkdirs();
                log.info("创建目录: {}, 成功: {}", tireUploadDir, created);
                if (!created) {
                    throw new IOException("无法创建目录: " + directory.getAbsolutePath());
                }
            }

            // 处理每个文件
            for (MultipartFile file : files) {
                String filePath = null;

                if (!file.isEmpty()) {
                    try {
                        log.info("处理文件: {}, 大小: {}", file.getOriginalFilename(), file.getSize());

                        // 生成唯一文件名
                        String originalFilename = file.getOriginalFilename();
                        String fileExtension = "";
                        if (originalFilename != null && originalFilename.contains(".")) {
                            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
                        } else {
                            fileExtension = ".jpg";
                        }
                        String uniqueFilename = System.currentTimeMillis() + "_" + UUID.randomUUID().toString() + fileExtension;

                        // 文件保存路径
                        filePath = tireUploadDir + File.separator + uniqueFilename;
                        log.info("文件保存路径: {}", filePath);

                        // 保存文件到磁盘 - 使用 transferTo 方法
                        File dest = new File(filePath);
                        try {
                            file.transferTo(dest);
                            log.info("文件保存到磁盘成功: {}", filePath);
                        } catch (IOException e) {
                            log.error("文件保存失败: {}", e.getMessage());
                            // 备用保存方法
                            saveFileAlternative(file, dest);
                        }

                        // 创建照片记录
                        TirePhoto tirePhoto = new TirePhoto();
                        tirePhoto.setFileName(originalFilename);
                        tirePhoto.setFilePath(filePath);
                        tirePhoto.setFileSize(file.getSize());
                        tirePhoto.setContentType(file.getContentType());
                        tirePhoto.setUploadDate(LocalDateTime.now());

                        // 关键：设置轮胎关联
                        tirePhoto.setTire(tire);
                        tirePhoto.setPhotoType("GENERAL");

                        log.info("准备保存照片记录到数据库，轮胎ID: {}", tire.getId());

                        // 保存到数据库
                        TirePhoto savedPhoto = tirePhotoRepository.save(tirePhoto);
                        savedPhotos.add(savedPhoto);
                        log.info("照片记录保存到数据库成功，ID: {}", savedPhoto.getId());

                    } catch (Exception e) {
                        log.error("处理照片 {} 时出错: {}", file.getOriginalFilename(), e.getMessage(), e);

                        // 删除可能已经保存的文件
                        if (filePath != null) {
                            try {
                                File failedFile = new File(filePath);
                                if (failedFile.exists()) {
                                    boolean deleted = failedFile.delete();
                                    log.info("删除失败的文件: {}, 成功: {}", filePath, deleted);
                                }
                            } catch (Exception ex) {
                                log.error("删除失败文件时出错: {}", ex.getMessage());
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            log.error("保存照片过程中发生严重错误: {}", e.getMessage(), e);
        }

        log.info("照片保存完成，总共保存了 {} 张照片", savedPhotos.size());
        return savedPhotos;
    }




    /**
     * 保存文件到磁盘
     */
    private void saveFileToDisk(MultipartFile file, File dest) throws IOException {
        try (InputStream inputStream = file.getInputStream();
             FileOutputStream outputStream = new FileOutputStream(dest)) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            System.out.println("文件保存成功: " + dest.getAbsolutePath());
        } catch (IOException e) {
            System.err.println("文件保存失败: " + e.getMessage());
            throw e;
        }
    }

    /**
     * 删除文件（如果存在）
     */
    private void deleteFileIfExists(String filePath) {
        try {
            File file = new File(filePath);
            if (file.exists()) {
                boolean deleted = file.delete();
                System.out.println("删除文件: " + filePath + ", 成功: " + deleted);
            }
        } catch (Exception ex) {
            System.err.println("删除文件时出错: " + ex.getMessage());
        }
    }



    /**
     * 备用文件保存方法
     */
    private void saveFileAlternative(MultipartFile file, File dest) throws IOException {
        try (InputStream inputStream = file.getInputStream();
             FileOutputStream outputStream = new FileOutputStream(dest)) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            System.out.println("使用备用方法保存文件成功: " + dest.getAbsolutePath());
        }
    }

    /**
     * 根据ID获取照片
     */
    public Optional<TirePhoto> getPhotoById(Long photoId) {
        return tirePhotoRepository.findById(photoId);
    }

    /**
     * 根据轮胎ID获取所有照片
     */
    public List<TirePhoto> getPhotosByTireId(Long tireId) {
        return tirePhotoRepository.findByTireId(tireId);
    }

    /**
     * 删除照片
     */
    public void deletePhoto(Long tireId, Long photoId) throws IOException {
        Optional<TirePhoto> photoOpt = tirePhotoRepository.findById(photoId);

        if (photoOpt.isPresent()) {
            TirePhoto photo = photoOpt.get();

            // 验证照片是否属于指定的轮胎
            if (!photo.getTire().getId().equals(tireId)) {
                throw new RuntimeException("照片不属于指定的轮胎");
            }

            // 删除磁盘上的文件
            Path filePath = Paths.get(photo.getFilePath());
            if (Files.exists(filePath)) {
                Files.delete(filePath);
                System.out.println("删除文件: " + filePath);
            }

            // 删除数据库记录
            tirePhotoRepository.delete(photo);
            System.out.println("删除照片记录: " + photoId);
        } else {
            throw new RuntimeException("照片不存在，ID: " + photoId);
        }
    }
}